﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using System.ServiceModel;
using Project.Dal.Base;
using System.Configuration;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using CNDreams.Server.Base;
using System.Reflection;
using Project.Server.Base;
using System.Web.Hosting;
using System.IO;
using System.ServiceModel.Activation;
using System.Security.Cryptography.X509Certificates;
using System.IdentityModel.Selectors;


namespace CNDreams.Server
{
	// Note: For instructions on enabling IIS6 or IIS7 classic mode, 
	// visit http://go.microsoft.com/?LinkId=9394801
	public class MvcApplication : System.Web.HttpApplication
	{
		public static List<ServiceHost> hosts = new List<ServiceHost>();
		protected void Application_Start()
		{
			HostingEnvironment.RegisterVirtualPathProvider(new ServicePathProvider());
			AreaRegistration.RegisterAllAreas();
			//WebApiConfig.Register(GlobalConfiguration.Configuration);
			FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
			RouteConfig.RegisterRoutes(RouteTable.Routes);

			//Nhibernate 配置
			NHibernateHelper.Configure();
		}


	}

	public class ServicePathProvider : VirtualPathProvider
	{
		public override VirtualFile GetFile(string virtualPath)
		{
			if (!this.IsServiceCall(virtualPath))
				return this.Previous.GetFile(virtualPath);
			return new ServiceFile(virtualPath);
		}

		private bool IsServiceCall(string virtualPath)
		{
			// Check if it is a wcf service call
			virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
			return (virtualPath.ToLower().EndsWith(".svc"));
		}

		public override bool FileExists(string virtualPath)
		{
			if (!this.IsServiceCall(virtualPath))
				return this.Previous.FileExists(virtualPath);
			return true;
		}
	}

	public class ServiceFile : VirtualFile
	{
		public ServiceFile(string virtualPath)
			: base(virtualPath)
		{ }

		public string GetCallingServiceName
		{
			get
			{
				// Return class name. srv_hello.svc => hello
				return base.VirtualPath.Replace("//", string.Empty);
			}
		}

		public string GetService()
		{

			string srv = this.GetCallingServiceName;
			// hello => Hello
			return srv[0].ToString().ToUpper() + srv.Substring(1);
		}

		public override Stream Open()
		{
			var serviceDef = new MemoryStream();
			var defWriter = new StreamWriter(serviceDef);
			// Write host definition
			defWriter.Write("<%@ ServiceHost Language=\"C#\" Debug=\"true\" Factory=\"CNDreams.Server.DynamicHostFactory, CNDreams.Server\" %>");
			defWriter.Flush();
			serviceDef.Position = 0;
			return serviceDef;
		}
	}

	public class DynamicHostFactory : ServiceHostFactory
	{
		public DynamicHostFactory() { }

		public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
		{
			string serviceName = baseAddresses[0].LocalPath.Substring(baseAddresses[0].LocalPath.LastIndexOf('/')).Replace("/", string.Empty).Replace(".svc", string.Empty);
			string iServiceName = "I" + serviceName;

			Assembly assemblyInterfaces = Assembly.Load("CNDreams.ServiceInterface");
			Type interfaceType = assemblyInterfaces.GetTypes().FirstOrDefault(x => x.Name.Equals(iServiceName, StringComparison.OrdinalIgnoreCase));
			if (interfaceType == null)
				return null;

			Type[] allServerTypes = Assembly.GetExecutingAssembly().GetTypes();
			Type implementedType = allServerTypes.FirstOrDefault(x => x.GetInterface(interfaceType.Name) != null);
			if (implementedType == null)
				return null;

			ServiceHost host = new ServiceHost(implementedType, baseAddresses);

			/* wsHttpBinding 绑定节点
			----------------------------------------------------------*/
			WSHttpBinding wsHttpBinding = new WSHttpBinding("wsHttpBinding-binding");
			host.AddServiceEndpoint(interfaceType, wsHttpBinding, "wsHttp");

			/* webHttpBinding 绑定节点
			----------------------------------------------------------*/
			WebHttpBinding webHttpBinding = new WebHttpBinding("webHttpBinding-binding");
			ServiceEndpoint serviceEndpoint = host.AddServiceEndpoint(interfaceType, webHttpBinding, "webHttp");
			serviceEndpoint.Behaviors.Add(new WebHttpBehavior()
			{
				AutomaticFormatSelectionEnabled = true,
				HelpEnabled = true
			});

			ServiceMetadataBehavior metaDataBehavior = new ServiceMetadataBehavior();
			metaDataBehavior.HttpGetEnabled = true;
			host.Description.Behaviors.Add(metaDataBehavior);
			host.Description.Behaviors.Add(new NHibernateInceptor());
			ServiceDebugBehavior debug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
			//ServiceCredentials serviceCredential = new ServiceCredentials();
			//serviceCredential.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
			//serviceCredential.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
			//serviceCredential.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectDistinguishedName, "CN=localhost");
			//host.Description.Behaviors.Add(serviceCredential);
			if (debug == null)
			{
				host.Description.Behaviors.Add(
					 new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
			}
			else
			{
				if (!debug.IncludeExceptionDetailInFaults)
					debug.IncludeExceptionDetailInFaults = true;
			}
			host.AddServiceEndpoint(typeof(IMetadataExchange), wsHttpBinding, "MEX");

			return host;
		}
	}

	public class CustomUserNameValidator : UserNamePasswordValidator
	{

		public override void Validate(string userName, string password)
		{
			//throw new NotImplementedException();
		}
	}
}